/*
 * Copyright (c)  2015~2020, xforceplus
 * All rights reserved.
 * Project:datacare-orm
 * Id: SQLManagerBuilder.java   2020-10-05 11-29-34
 * Author: Evan
 */
package cn.datacare.orm.manager.impl;

import cn.datacare.orm.connection.ConnectionSource;
import cn.datacare.orm.conversion.DefaultNameConversion;
import cn.datacare.orm.conversion.NameConversion;
import cn.datacare.orm.dialect.Dialect;
import cn.datacare.orm.dialect.MySQLDialect;
import cn.datacare.orm.interceptor.DebugInterceptor;
import cn.datacare.orm.interceptor.Interceptor;
import cn.datacare.orm.loader.ClassPathLoader;
import cn.datacare.orm.loader.SQLLoader;
import org.apache.commons.collections4.CollectionUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toMap;

/**
 * <p>
 * Title:
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: 2015~2020
 * </p>
 * <p>
 * Company/Department: xforceplus
 * </p>
 *
 * @author Evan
 * <b>Creation Time:</b> 2020-10-05 11-29-34
 * @since V1.0
 */
public class SQLManagerBuilder {
    /**
     * 额外的beetl配置属性
     */
    private Properties properties;
    /***
     * 拦截器
     */
    private Interceptor[] interceptors;
    /**
     * 数据库默认的shcema，对于单个schema应用，无需指定，但多个shcema，需要指定默认的shcema
     */
    private String defaultSchema;

    private Dialect dialect;

    /**
     * sql加载
     */
    private SQLLoader sqlLoader;

    /**
     * 名字转换器
     */
    private NameConversion nc;

    /**
     * 数据库连接管理
     */
    private ConnectionSource ds;

    /**
     * 拦截器
     */
    private List<Interceptor> interceptorList = new LinkedList<>();

    /**
     * 构建函数
     *
     * @param ds 连接器
     */
    SQLManagerBuilder(ConnectionSource ds) {
        this.ds = ds;
    }


    public SQLManager build() {
        this.dialect=this.getDialect();
        this.sqlLoader=this.getSqlLoader();
        this.nc=this.getNc();
        this.interceptors=this.getInterceptors();
        this.properties=this.getProperties();
        this.defaultSchema=this.getDefaultSchema();
        SQLManager manager = new SQLManager(dialect, sqlLoader, ds, nc, interceptors, defaultSchema, properties, null);
        return manager;
    }

    /**
     * 添加拦截器，不会与inters冲突，只会追加
     *
     * @param interceptor 拦截器
     * @return this
     */
    public SQLManagerBuilder addInterceptor(Interceptor interceptor) {
        this.interceptorList.add(interceptor);
        return this;
    }


    /**
     * 添加 DebugInterceptor 不是必须的，但可以通过它查看sql执行情况 <BR>
     * 不会与inters冲突, 只会追加
     *
     * @return this
     */
    public SQLManagerBuilder addInterDebug() {
        this.interceptorList.add(new DebugInterceptor());
        return this;
    }

    /***
     * Beetl 额外的Beetl配置
     * @return Properties
     */
    private Properties getProperties() {
        if (this.properties == null) {
            this.properties = new Properties();
        }
        return this.properties;
    }


    private String getDefaultSchema() {
        return this.defaultSchema;
    }

    /**
     * 设置defaultSchema
     *
     * @param defaultSchema defaultSchema
     * @return this
     */
    public SQLManagerBuilder defaultSchema(String defaultSchema) {
        this.defaultSchema = defaultSchema;
        return this;
    }


    private Interceptor[] getInterceptors() {
        if (this.interceptors == null) {
            this.interceptors = new Interceptor[]{};
        }
        if (CollectionUtils.isEmpty(this.interceptorList)) {
            return interceptors;
        }
        //接收转换
        Map<String, Interceptor> interceptorMap = interceptorList
                .stream()
                .collect(toMap(e -> e.getClass().getName(), Interceptor -> Interceptor));
        //接收转换
        interceptorMap.putAll(Stream.of(this.interceptors)
                .collect(toMap(e -> e.getClass().getName(), Interceptor -> Interceptor)));
        //集合转换数组
        this.interceptors = interceptorMap.entrySet().stream()
                .map(Map.Entry::getValue)
                .toArray(Interceptor[]::new);
        return interceptors;
    }

    /***
     * 不是必须的，但可以通过它查看sql执行情况
     * @param interceptors
     * @return
     */
    public SQLManagerBuilder interceptors(Interceptor[] interceptors) {
        this.interceptors = interceptors;
        return this;
    }

    private Dialect getDialect() {
        if (this.dialect == null) {
            this.dialect = new MySQLDialect();
        }
        return this.dialect;
    }

    public SQLManagerBuilder dialect(Dialect dialect) {
        this.dialect = dialect;
        return this;
    }

    private SQLLoader getSqlLoader(){
        if(this.sqlLoader==null){
             this.sqlLoader=new ClassPathLoader();
        }
        return  this.sqlLoader;
    }


    public  SQLManagerBuilder sqlLoader(SQLLoader sqlLoader){
        this.sqlLoader=sqlLoader;
        return  this;
    }

    private  NameConversion getNc(){
        if(nc==null){
            nc=new DefaultNameConversion();
        }
        return  this.nc;
    }

    public SQLManagerBuilder nc(NameConversion nc){
        this.nc=nc;
        return this;
    }
}
